package com.dream.libxrec.camera;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.ImageFormat;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureRequest;
import android.media.Image;
import android.media.ImageReader;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.util.Log;
import android.util.Size;
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import com.luoye.bzyuvlib.BZYUVUtil;
import java.util.Arrays;

public class XCamera2 extends ICamera{

    private CameraDevice mCamera;
    private final Handler mMainHandler = new Handler(Looper.getMainLooper());
    private final HandlerThread mEncoderThread = new HandlerThread(
            "EncoderThread");
    private Handler mEncoderHandler;
    private ImageReader mImageReader = null;
    private CameraCaptureSession mCameraCaptureSession = null;

    private final BZYUVUtil mBzyuvUtil = new BZYUVUtil();//libyuv封装库
    private int mFps = 15;

    private volatile boolean isGetSteam = false;//是否正常取流中

    public XCamera2(){}

    /**
     * 初始化
     * @param ct 上下文
     * @param cameraID 摄像头ID
     * @param size 分辨率
     */
    @Override
    public void init(Context ct, String cameraID, Size size,
                     int rotation,boolean isMirror){

        //按照摄像头分辨率进行初始化
        mImageReader =
                ImageReader.newInstance(size.getWidth(),
                        size.getHeight(),
                        ImageFormat.YUV_420_888, 2);

        super.init(ct,cameraID,size,rotation,isMirror);

        Log.i("hhw",
                "w:"+mCameraSize.getWidth()+"h:"+mCameraSize.getHeight()+"rotation:"+rotation);
    }

    @Override
    public boolean isRun() {
        return isGetSteam;
    }


    @Override
    public void setFps(int fps) {
        this.mFps = fps;
    }

    @Override
    public void start(){
        initHandler();
        openCamera();
    }

    private void openCamera(){
        if (ActivityCompat.checkSelfPermission(mContext,
                Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED){
            return;
        }

        CameraManager manager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);

        //初始化ImageReader，用于后续获取预览数据帧
        initImageReader();

        try {
            manager.openCamera(mCameraID, new CameraDevice.StateCallback() {
                @Override
                public void onOpened(@NonNull CameraDevice camera) {
                    mCamera = camera;
                    startPreview();
                }

                @Override
                public void onDisconnected(@NonNull CameraDevice camera) {

                }

                @Override
                public void onError(@NonNull CameraDevice camera, int error) {

                }
            }, mEncoderHandler);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void initHandler() {
        mEncoderThread.start();
        mEncoderHandler = new Handler(mEncoderThread.getLooper());
    }

    private void initImageReader() {
        try {
            final int width = mCameraSize.getWidth();
            final int height = mCameraSize.getHeight();

            Log.i("hhw",
                    "摄像头ID:"+mCameraID+"w:"+width+";h:"+height);

            mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
                @Override
                public void onImageAvailable(ImageReader reader) {
                    synchronized (XCamera2.this){
                        isGetSteam = true;
                        Image image =  reader.acquireNextImage();
//                        long start = System.nanoTime();
                        byte[] data =
                                mBzyuvUtil.preHandleYUV420(image,
                                        isMirror,
                                        mRotation);

                        if (mImageAvailableListener != null){
                            mImageAvailableListener.onImageAvailable(mCameraID,data,TYPE_I420,width,height);
                        }

//                        Log.i("Test",
//                                "单帧耗时("+width+"*"+height+")："+(System.nanoTime() - start)/1000000);
                        image.close();
                    }
                }
            }, mEncoderHandler);

        }catch (Exception e){
            e.printStackTrace();
        }
    }

    private void startPreview() {
        try {
            mCamera.createCaptureSession(Arrays.asList(
                    mImageReader.getSurface()), new CameraCaptureSession.StateCallback() {
                @Override
                public void onConfigured(@NonNull CameraCaptureSession session) {
                    try {
                        CaptureRequest.Builder captureRequestBuilder = mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
                        captureRequestBuilder.addTarget(mImageReader.getSurface());
                        //设置帧率，单位为纳秒
                        captureRequestBuilder.set(CaptureRequest.SENSOR_FRAME_DURATION, 1000000000L/mFps);
                        session.setRepeatingRequest(captureRequestBuilder.build(), null, mMainHandler);
                        mCameraCaptureSession = session;
                    } catch (CameraAccessException e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void onConfigureFailed(@NonNull CameraCaptureSession session) {

                }
            }, mEncoderHandler);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 关闭视频及音频的采集，结束编码器及MP4封装
     */
    @Override
    public void stop(){
        isGetSteam = false;
        try {
            //停止预览，不再获取数据
            if (mCameraCaptureSession != null){
                mCameraCaptureSession.stopRepeating();
                mCameraCaptureSession = null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        try {
            mCamera.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
